package com.bizmda.bizsip.converter;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import com.bizmda.bizsip.common.BizException;
import com.bizmda.bizsip.common.BizResultEnum;
import com.bizmda.bizsip.config.AbstractSinkConfig;
import com.bizmda.bizsip.config.CommonSourceConfig;
import com.bizmda.bizsip.config.SinkConfigMapping;
import com.bizmda.bizsip.config.SourceConfigMapping;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;

/**
 * 格式转换器处理类
 *
 * @author shizhengye
 */
@Slf4j
public class Converter {
    private AbstractConverter abstractConverter;

    /**
     * 根据source-id获取格式转换器调用接口
     *
     * @param sourceId 指定Source层模块的source-id
     * @return 格式转换器调用接口
     * @throws BizException BizException
     */
    public static Converter getSourceConverter(String sourceId) throws BizException {
        log.debug("获取Source层格式转换器: Converter.getSourceConverter({})", sourceId);
        Converter converter = new Converter();
        SourceConfigMapping sourceConfigMapping = SpringUtil.getBean(SourceConfigMapping.class);
        CommonSourceConfig sourceConfig = sourceConfigMapping.getSourceId(sourceId);
        if (sourceConfig == null) {
            throw new BizException(BizResultEnum.SOURCE_ID_NOTFOUND, "source:" + sourceId);
        }
        log.trace("Source模块[{}]Converter配置: {}", sourceId, sourceConfig.getConverterMap());
        String converterType = (String) sourceConfig.getConverterMap().get("type");
        Class<? extends AbstractConverter> clazz = (Class<? extends AbstractConverter>) AbstractConverter.CONVERTER_TYPE_MAP.get(converterType);
        if (clazz == null) {
            throw new BizException(BizResultEnum.CONVERTOR_NOT_SET);
        }

        try {
            converter.abstractConverter = clazz.getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException
                | InvocationTargetException | NoSuchMethodException e) {
            throw new BizException(BizResultEnum.CONVERTOR_CREATE_ERROR, e);
        }
        converter.abstractConverter.init(sourceConfigMapping.getConfigPath(), sourceConfig.getConverterMap());

        return converter;
    }

    /**
     * 根据sink-id获取格式转换器调用接口
     *
     * @param sinkId Sink层模块的sink-id
     * @return 格式转换器调用接口
     * @throws BizException BizException
     */
    public static Converter getSinkConverter(String sinkId) throws BizException {
        log.debug("获取Sink层格式转换器: Converter.getSinkConverter({})", sinkId);
        Converter converter = new Converter();
        SinkConfigMapping sinkConfigMapping = SpringUtil.getBean(SinkConfigMapping.class);
        AbstractSinkConfig sinkConfig;
        try {
            sinkConfig = sinkConfigMapping.getSinkConfig(sinkId);
        } catch (BizException e) {
            log.error("获取Sink配置出错!", e);
            return null;
        }
        if (sinkConfig == null) {
            throw new BizException(BizResultEnum.SINK_NOT_SET, "sinkId[" + sinkId + "]在sink.yml中没有配置");
        }
        log.trace("Sink服务[{}]Converter配置: {}", sinkId, sinkConfig.getConverterMap());
        if (sinkConfig.getConverterMap() == null) {
            converter.abstractConverter = null;
            return converter;
        }
        String converterType = (String) sinkConfig.getConverterMap().get("type");
        Class<Object> clazz = (Class<Object>) AbstractConverter.CONVERTER_TYPE_MAP.get(converterType);
        if (clazz == null) {
            throw new BizException(BizResultEnum.CONVERTOR_NOT_SET);
        }
        try {
            converter.abstractConverter = (AbstractConverter) clazz.getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            throw new BizException(BizResultEnum.CONVERTOR_CREATE_ERROR, e);
        }
        converter.abstractConverter.init(sinkConfigMapping.getConfigPath(), sinkConfig.getConverterMap());

        return converter;
    }

    /**
     * 获取底层格式转换器
     *
     * @return 底层格式转换器对象
     */
    public AbstractConverter getConverter() {
        return this.abstractConverter;
    }

    /**
     * 消息报文的解包
     *
     * @param inMessage 待解包的消息报文
     * @return 解包完成后的消息报文
     * @throws BizException Biz-SIP应用异常
     */
    public JSONObject unpack(byte[] inMessage) throws BizException {
        return this.abstractConverter.unpack(inMessage);
    }

    /**
     * 消息报文的打包
     *
     * @param inMessage 待打包的消息报文
     * @return 打包完成后的消息报文
     * @throws BizException Biz-SIP应用异常
     */
    public byte[] pack(JSONObject inMessage) throws BizException {
        return this.abstractConverter.pack(inMessage);
    }

}
